#     TextLocutor
#     Copyright (C) 2009  Jose Ignacio Naranjo Hernandez (joseignacio.naranjo@gmail.com)

#     This program is free software: you can redistribute it and/or modify
#     it under the terms of the GNU Affero General Public License as
#     published by the Free Software Foundation, either version 3 of the
#     License, or (at your option) any later version.

#     This program is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU Affero General Public License for more details.

#     You should have received a copy of the GNU Affero General Public License
#     along with this program.  If not, see <http://www.gnu.org/licenses/>.

# python imports
import logging
from os import path
from urllib import unquote, unquote_plus
from xml.dom import minidom

# django imports
from django.utils import simplejson

# google imports
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
import google.appengine.api.users
from google.appengine.ext import db

# textlocutor imports
import core_settings
import core
from core.models import CoreUser
from core.utils import send_message
from football_scores.models import Team, League, Country, UserTeamProperties, Match
from football_scores.exceptions import *

class MainPage(core.BaseRequestHandler):
    def get(self):
        user = google.appengine.api.users.get_current_user()
        info = self.init_fixtures(user)
        if self.bad_init:
            return

        coreuser = CoreUser.all().filter('user =', user).get()
        template_values = {
            'user' : coreuser,
            'ext_list': core_settings.EXTRA_APPS,
            'base_url': self.request.host_url,
            'logout_url': google.appengine.api.users.CreateLogoutURL(self.request.uri),
            }
        if info:
            template_values.update(info)
        self.generate(template_values, 'football_scores_main.html')


class EventHandler(webapp.RequestHandler):
    def post(self, *args):
        if self.request.POST.has_key('user'): # Send the message to the user
            if self.request.POST['score'] == 'Fin': # End of match
                match = Match.get_or_insert(self.request.POST['home'],
                                            self.request.POST['visitor'])
                if match.score is None:
                    message = '%s - %s : Fin : %s' % (self.request.POST['home'],
                                                      self.request.POST['visitor'],
                                                      'desconocido')
                else:
                    message = '%s - %s : Fin : %s' % (self.request.POST['home'],
                                                      self.request.POST['visitor'],
                                                      match.score)
            else:
                if self.request.POST['scorer'] == 'None':
                    self.request.POST['scorer'] = ''
                message = '%s - %s : %s %s' % (self.request.POST['home'],
                                               self.request.POST['visitor'],
                                               self.request.POST['score'],
                                               self.request.POST['scorer'])

            logging.info(message + " -- " + self.request.POST['user'])

            user = google.appengine.api.users.User(self.request.POST['user'])
            coreuser = CoreUser.all().filter('user =', user).get()
            if not coreuser:
                logging.error("The user %s seems not to exist" % self.request.POST['user'])
                return
            send_message(coreuser, message)

        elif self.request.POST['score'] == '1 HF':
            match = Match.get_or_insert(self.request.POST['home'],
                                        self.request.POST['visitor'],
                                        '0-0')

        else: # Send the list of users interested in the event
            # store the data info
            match = Match.get_or_insert(self.request.POST['home'],
                                        self.request.POST['visitor'])

            users = ''
            utps_home = None
            utps_visitor = None
            # Send to the fs feeder the list of users interested in the goal
            try:
                utps_home = match.home.userteamproperties_set.fetch(1000)
            except AttributeError:
                utps_home = []
            try:
                utps_visitor = match.visitor.userteamproperties_set.fetch(1000)
            except AttributeError:
                utps_visitor = []

            utps = utps_home + utps_visitor
            
            if self.request.POST['score'] == 'Fin': # End of match
                for u in utps:
                    users += '&%s' % u.coreuser.user.email()
                    # TODO: Create message
                logging.debug('End of match : %s - %s' % (self.request.POST['home'],
                                                          self.request.POST['visitor']))
            else:
                if match.is_new_goal(self.request.POST['score']):
                    for u in utps:
                        if (not u.only_fscore) and ((not u.scorer) or ((self.request.POST['scorer'] != '') and u.scorer)):
                            users += '&%s' % u.coreuser.user.email()
                    match.score = self.request.POST['score']
                    match.last_scorer = self.request.POST['scorer']
                    match.put()
                    logging.debug('New goal - %s:%s:%s:%s' % (match.home_str,
                                                              match.visitor_str,
                                                              match.score,
                                                              match.last_scorer))
                elif (match.is_last_goal(self.request.POST['score']) and (len(match.last_scorer) <= 1) and (len(self.request.POST['scorer']) > 1)):
                    for u in utps:
                        if (not u.only_fscore) and u.scorer:
                            users += '&%s' % u.coreuser.user.email()
                    match.last_scorer = self.request.POST['scorer']
                    match.put()
                    logging.debug('New scorer - %s:%s:%s:%s' % (match.home_str,
                                                                match.visitor_str,
                                                                match.score,
                                                                match.last_scorer))
                else:
                    logging.debug('Event known - %s:%s:%s:%s' % (self.request.POST['home'],
                                                                 self.request.POST['visitor'],
                                                                 self.request.POST['score'],
                                                                 self.request.POST['scorer']))

            # the first character is useless
            if users != '':
                logging.info(users[1:len(users)])
            self.response.out.write(users[1:len(users)])


class TeamFixture(webapp.RequestHandler):
    def post(self, *args):
        """ Receive a XML file with the fixtures of a country """
        xmldoc = minidom.parseString(self.request.body)

        country_node = xmldoc.firstChild

        country = Country.all().filter('name =', country_node.attributes['id'].value).get()
        if not country:
            country = Country(name=country_node.attributes['id'].value)
            country.put()
            logging.info("Added %s" % country)

        for league_node in country_node.getElementsByTagName('league'):
            league = League.all().filter('name =', country_node.attributes['id'].value
                                         + " - " +  league_node.attributes['id'].value).get()
            if not league:
                league = League(name="%s - %s" % (country_node.attributes['id'].value, 
                                                  league_node.attributes['id'].value))
                league.put()
                logging.info("Added %s" % league)

            if not (league.key() in country.leagues):
                country.leagues.append(league.key())
            
            for team_node in league_node.getElementsByTagName('team'):
                team = Team.all().filter('name =', team_node.firstChild.data).get()

                if team is None:
                    team = Team(name=team_node.firstChild.data)
                    team.put()
                    logging.info("Added %s" % team)                

                if not (team.key() in league.teams):
                    league.teams.append(team.key())
            league.put()
        country.put()


class CountryResource(core.BaseRequestHandler):

    def get(self):
        list_countries = []
        for c in Country.all():
            list_countries.append(c.name)
        response = {'list_countries': list_countries}
        self.response.out.write(simplejson.dumps(response))            


class TeamUser(core.BaseRequestHandler):

    def get(self):
        user = google.appengine.api.users.get_current_user()
        coreuser = CoreUser.all().filter('user =', user).get()
        teams = coreuser.userteamproperties_set
        list_teams = []
        for t in teams:
            entry = {'name': t.team.name, 'scorer': t.scorer, 'final_score': t.only_fscore}
            list_teams.append(entry)
        response = {'list_teams': list_teams}
        self.response.out.write(simplejson.dumps(response))

    def put(self, param):
        user = google.appengine.api.users.get_current_user()
        coreuser = CoreUser.all().filter('user =', user).get()
        team_str = unquote(param)

        try:
            team = UserTeamProperties.add_user_team(coreuser, team_str)
            message = "You have added %s to your list of teams." % team_str
            logging.debug(message)
            response = {'message': message,
                        'team': {'name': team_str, 'scorer': team.scorer, 'final_score': team.only_fscore}}
            self.response.out.write(simplejson.dumps(response))
        except FootballScoresError, e:
            if e.__class__ == TeamNotExists:
                message = "%s was not found. No team added." % team_str
                team_str = 'error'
            elif e.__class__ == TeamSelectedError:
                message = "%s is already in your list of teams." % team_str
                team_str = 'error'
            elif e.__class__ == TeamsExceededError:
                message = "You can not add %s because you have already selected the maximum number of teams." % team_str
                team_str = 'error'
            logging.debug(message)
            response = {'message': message,
                        'team': team_str}
            self.response.out.write(simplejson.dumps(response))

    def delete(self, param):    
        user = google.appengine.api.users.get_current_user()
        coreuser = CoreUser.all().filter('user =', user).get()
        team_str = unquote(param)

        try:
            UserTeamProperties._delete(coreuser, team_str)
        except FootballScoresError, e:
            if e.__class__ == TeamNotExists:
                message = "%s was not found. No team deleted." % team_str
            elif e.__class__ == TeamNotFound:
                message = "%s has not been found in your team list." % team_str
        else:
            message = "%s has been deleted from your list of teams." % team_str
        logging.debug(message)
        response = {'message': message,
                    'team': team_str}
        self.response.out.write(simplejson.dumps(response))


class ViewCountry(core.BaseRequestHandler):

    def get(self, param):
        country_str = unquote(param)
        country = Country.all().filter('name =', country_str).get()

        leagues = []
        if country is not None:
            leagues = [db.get(l) for l in country.leagues]
        
        list_leagues = []
        for l in leagues:
            list_leagues.append(l.name)
        response = {'list_leagues': list_leagues}
        self.response.out.write(simplejson.dumps(response))


class ViewLeague(core.BaseRequestHandler):

    def get(self, param):
        league_str = unquote(param)
        league = League.all().filter('name =', league_str).get()

        teams = []
        if league is not None:
            teams = [db.get(t) for t in league.teams]

        list_teams = []
        for t in teams:
            list_teams.append(t.name)
        response = {'list_teams': list_teams}
        self.response.out.write(simplejson.dumps(response))


class TeamProperties(core.BaseRequestHandler):

    def get(self, team_str):
        user = google.appengine.api.users.get_current_user()
        coreuser = CoreUser.all().filter('user =', user).get()
        teams = coreuser.userteamproperties_set
        for t in teams:
            if t.team.name == team_str:
                entry = {'name': t.team.name, 'scorer': t.scorer, 'final_score': t.only_fscore}
                self.response.out.write(simplejson.dumps(entry))

    def post(self, team_str):
        user = google.appengine.api.users.get_current_user()
        coreuser = CoreUser.all().filter('user =', user).get()
        teams = coreuser.userteamproperties_set
        team_str_aux = unquote(team_str)
        for t in teams:
            if t.team.name == team_str_aux:
                if self.request.POST['prop'] == 'scorer':
                    t.only_fscore = False
                    t.scorer = True
                    t.put()
                elif self.request.POST['prop'] == 'score':
                    t.only_fscore = True
                    t.scorer = False
                    t.put()
                else:
                    t.only_fscore = False
                    t.scorer = False
                    t.put()
                entry = {'name': t.team.name, 'scorer': t.scorer, 'final_score': t.only_fscore}
                self.response.out.write(simplejson.dumps(entry))
